sources: Vec<PathSource>,
hashes: HashMap<(String, String), String>, // (name, vers) => cksum
cache: HashMap<String, Vec<(Summary, bool)>>,
+ updated: bool,
}
#[deriving(Decodable)]
sources: Vec::new(),
hashes: HashMap::new(),
cache: HashMap::new(),
+ updated: false,
}
}
.default_features(default_features)
.features(features))
}
-}
-impl<'a, 'b> Registry for RegistrySource<'a, 'b> {
- fn query(&mut self, dep: &Dependency) -> CargoResult<Vec<Summary>> {
- let summaries = try!(self.summaries(dep.get_name()));
- let mut summaries = summaries.iter().filter(|&&(_, yanked)| {
- dep.get_source_id().get_precise().is_some() || !yanked
- }).map(|&(ref s, _)| s.clone()).collect::<Vec<_>>();
- summaries.query(dep)
- }
-}
+ /// Actually perform network operations to update the registry
+ fn do_update(&mut self) -> CargoResult<()> {
+ if self.updated { return Ok(()) }
-impl<'a, 'b> Source for RegistrySource<'a, 'b> {
- fn update(&mut self) -> CargoResult<()> {
try!(self.config.shell().status("Updating",
format!("registry `{}`", self.source_id.get_url())));
let repo = try!(self.open());
log!(5, "[{}] updating to rev {}", self.source_id, oid);
let object = try!(repo.find_object(oid, None));
try!(repo.reset(&object, git2::Hard, None, None));
+ self.updated = true;
+ self.cache.clear();
+ Ok(())
+ }
+}
+
+impl<'a, 'b> Registry for RegistrySource<'a, 'b> {
+ fn query(&mut self, dep: &Dependency) -> CargoResult<Vec<Summary>> {
+ // If this is a precise dependency, then it came from a lockfile and in
+ // theory the registry is known to contain this version. If, however, we
+ // come back with no summaries, then our registry may need to be
+ // updated, so we fall back to performing a lazy update.
+ if dep.get_source_id().get_precise().is_some() &&
+ try!(self.summaries(dep.get_name())).len() == 0 {
+ try!(self.do_update());
+ }
+
+ let summaries = try!(self.summaries(dep.get_name()));
+ let mut summaries = summaries.iter().filter(|&&(_, yanked)| {
+ dep.get_source_id().get_precise().is_some() || !yanked
+ }).map(|&(ref s, _)| s.clone()).collect::<Vec<_>>();
+ summaries.query(dep)
+ }
+}
+
+impl<'a, 'b> Source for RegistrySource<'a, 'b> {
+ fn update(&mut self) -> CargoResult<()> {
+ // If we have an imprecise version then we don't know what we're going
+ // to look for, so we always atempt to perform an update here.
+ //
+ // If we have a precise version, then we'll update lazily during the
+ // querying phase.
+ if self.source_id.get_precise().is_none() {
+ try!(self.do_update());
+ }
Ok(())
}
use support::{project, execs, cargo_dir};
use support::{UPDATING, DOWNLOADING, COMPILING, PACKAGING, VERIFYING};
-use support::paths::PathExt;
+use support::paths::{mod, PathExt};
use support::registry as r;
use hamcrest::assert_that;
r::mock_pkg("bar", "0.0.2", []);
assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
- execs().with_status(0).with_stdout(format!("\
-{updating} registry `[..]`
-", updating = UPDATING).as_slice()));
+ execs().with_status(0).with_stdout(""));
})
test!(lockfile_locks_transitively {
r::mock_pkg("bar", "0.0.2", [("baz", "*")]);
assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
- execs().with_status(0).with_stdout(format!("\
-{updating} registry `[..]`
-", updating = UPDATING).as_slice()));
+ execs().with_status(0).with_stdout(""));
})
test!(yanks_are_not_used {
r::mock_pkg_yank("bar", "0.0.1", [], true);
assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
- execs().with_status(0).with_stdout(format!("\
-{updating} registry `[..]`
-", updating = UPDATING).as_slice()));
+ execs().with_status(0).with_stdout(""));
assert_that(p.process(cargo_dir().join("cargo")).arg("update"),
execs().with_status(101).with_stderr("\
version required: *
"));
})
+
+test!(update_with_lockfile_if_packages_missing {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/main.rs", "fn main() {}");
+ p.build();
+
+ r::mock_pkg("bar", "0.0.1", []);
+ assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
+ execs().with_status(0));
+ p.root().move_into_the_past().unwrap();
+
+ fs::rmdir_recursive(&paths::home().join(".cargo/registry")).unwrap();
+ assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
+ execs().with_status(0).with_stdout(format!("\
+{updating} registry `[..]`
+{downloading} bar v0.0.1 (the package registry)
+", updating = UPDATING, downloading = DOWNLOADING).as_slice()));
+})
+
+test!(update_lockfile {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/main.rs", "fn main() {}");
+ p.build();
+
+ r::mock_pkg("bar", "0.0.1", []);
+ assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
+ execs().with_status(0));
+
+ r::mock_pkg("bar", "0.0.2", []);
+ fs::rmdir_recursive(&paths::home().join(".cargo/registry")).unwrap();
+ assert_that(p.process(cargo_dir().join("cargo")).arg("update")
+ .arg("-p").arg("bar"),
+ execs().with_status(0).with_stdout(format!("\
+{updating} registry `[..]`
+", updating = UPDATING).as_slice()));
+
+ assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
+ execs().with_status(0).with_stdout(format!("\
+{downloading} [..] v0.0.2 (the package registry)
+{compiling} bar v0.0.2 (the package registry)
+{compiling} foo v0.0.1 ({dir})
+", downloading = DOWNLOADING, compiling = COMPILING,
+ dir = p.url()).as_slice()));
+})